﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StyleMVVM.Data;
using StyleMVVM.DependencyInjection;
using StyleMVVM.UnitTests.TestClasses.ValidationObjects.Automobile;
using StyleMVVM.Validation;
using StyleMVVM.Validation.Impl;
using StyleMVVM.Validation.Impl.Fluent;
#if NETFX_CORE
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using Windows.ApplicationModel.Resources;

#else
using Microsoft.VisualStudio.TestTools.UnitTesting;

#endif

namespace StyleMVVM.UnitTests.Validation.Fluent
{
	[TestClass]
	public class CombinationLogicTests : BaseTestClass
	{
		[TestMethod]
		public void TestAndLogic()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).GreaterThanOrEqualTo.Value(4).And.
			           Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(2);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 3, MaxPassengers = 1 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 4;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 2;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void TestOrLogic()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.Wheels).GreaterThanOrEqualTo.Value(4).Or.
			           Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(2);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 3, MaxPassengers = 1 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 4;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);

			newTruck.Wheels = 3;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 2;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);

			newTruck.Wheels = 4;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void IfThenTest()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.If.Property(x => x.Wheels).GreaterThanOrEqualTo.Value(8).Then.
			           Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(6);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 7, MaxPassengers = 1 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);

			newTruck.Wheels = 8;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 6;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void IfThenElseTest()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.If.Property(x => x.Wheels).GreaterThanOrEqualTo.Value(8).Then.
			           Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(6).Else.
			           Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(2);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 7, MaxPassengers = 1 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 2;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);

			newTruck.Wheels = 8;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 6;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void WhenTest()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(6).When.
			           Property(x => x.Wheels).GreaterThanOrEqualTo.Value(8);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 7, MaxPassengers = 1 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);

			newTruck.Wheels = 8;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 6;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}

		[TestMethod]
		public void UnlessTest()
		{
			ResourceLoader fluentResources = new ResourceLoader("StyleMVVM.CSharp/FluentResources");
			FluentRule<Truck> wheelsRule = new FluentRule<Truck>(Container.Locate<IReflectionService>(), "WheelRule");

			wheelsRule.Property(x => x.MaxPassengers).GreaterThanOrEqualTo.Value(6).Unless.
			           Property(x => x.Wheels).GreaterThanOrEqualTo.Value(8);

			wheelsRule.Compile(fluentResources);

			Truck newTruck = new Truck { Wheels = 7, MaxPassengers = 1 };

			RuleExecutionContext context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.MaxPassengers = 6;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);

			newTruck.MaxPassengers = 5;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Invalid, context.State);

			newTruck.Wheels = 8;

			context = new RuleExecutionContext(newTruck);

			wheelsRule.Validate(context);

			Assert.AreEqual(ValidationState.Valid, context.State);
		}
	}
}